package dataStructures.list;

import java.util.Iterator;

/**
 *
 * @author Shimu
 */
public class SinglelyLinkedListWithSentinel<T> implements Iterable<T> {

    private int size;
    private SinglelyLinkedNode<T> first, last;

    public SinglelyLinkedListWithSentinel() {
        this.size = 0;

        this.first = SinglelyLinkedNode.sentinel;
        this.last = first;

        /*
         *        first      last
         *            \      /
         *             v    v
         *      |-> sentinel(null) -|
         *      ---------------------
         */

    }

    public SinglelyLinkedListWithSentinel(T firstData) {
        this();
        
        // Adds the firstData to the front
        this.first = 
                new SinglelyLinkedNode<T>(firstData, SinglelyLinkedNode.sentinel);
        //this.last = this.first;
        size++;
    }

    /**
     * Adds to the front of the linked list
     * @param data 
     */
    public void addFirst(T data) {
        SinglelyLinkedNode<T> next = this.first;
        this.first = new SinglelyLinkedNode<T>(data, next);
        size++;
    }
    /**
     * Adds to the back of the linked list
     * @param data 
     */
    public final void addLast(T data) {
        SinglelyLinkedNode<T> oldLast = this.last;
        this.last = 
                new SinglelyLinkedNode<T>(data, SinglelyLinkedNode.sentinel);
        oldLast.next = this.last;
        size++;
    }

    /**
     * Returns and removes an item from the front of the LinkedList.
     *
     * @return
     */
    public T removeFirst() {
        T data = first.data;
        first = first.next;
        return data;
        //size--;
    }

    /**
     * Returns and removes the item at the back of the LinkedList
     * @return 
     
    public T removeLast(){
        
    
     * */
    
    /**
     * Returns true if this LinkedList has no more elements, false otherwise.
     * @return true if this LinkedList is empty.
     */
    public boolean isEmpty() {
        return (first.equals(SinglelyLinkedNode.sentinel));
    }

    /**
     * Returns the number of elements in this LinkedList.
     * @return the size of this LinkedList.
     */
    public int getSize() {
        return this.size;
    }

    public Iterator<T> iterator() {
        return new SinglelyLinkedListIterator<T>();
    }

    private class SinglelyLinkedListIterator<T> implements Iterator<T> {

        private SinglelyLinkedNode<T> current;

        private SinglelyLinkedListIterator() {
            this.current = (SinglelyLinkedNode<T>) first;
        }

        public boolean hasNext() {
            return (current != SinglelyLinkedNode.sentinel);
        }

        public T next() {
            T returnData = current.data;
            current = current.next;
            return returnData;
        }

        public void remove() {
        }
    }
}
